<?php
/**
 * Created by PhpStorm.
 * User: i5_131009a
 * Date: 2015/12/21
 * Time: 11:36
 */

require_once GM_LIBRARY."/dataProcess.class.php";

/**
 * Class PHPImport
 */
class PHPImport {
    protected $sourceFormatDir;
    protected $sourceFileDir;
    protected $sourceFormatFileList;
    protected $sourceFormatExt = "json";
    protected $databaseLink = null;
    protected $dataProcess = null;
    protected $configArray = null;
    protected $haveError = false;
    const IMPORT_DATA_MODEL_STRICT = 1;
    const IMPORT_DATA_MODEL_TOLERANCE = 2;
    protected $importModel = self::IMPORT_DATA_MODEL_STRICT;

    function __construct($sourceFormatDir,$importModel = null,$sourceFileDir = null)
    {
        $this->sourceFileDir = $sourceFileDir;
        $this->sourceFormatDir = $sourceFormatDir;
        $this->setSourceFormatFileList();
        if(!is_null($importModel)){
            if($importModel != self::IMPORT_DATA_MODEL_STRICT && $importModel != self::IMPORT_DATA_MODEL_TOLERANCE ){
                throw new Exception("Import model not find");
            }
            $this->importModel = $importModel;
        }

    }

    /**
     * @param $sourceFilePath
     * @param $sourceFormatName
     * @return bool
     */
    function loadSourceConfig($sourceFilePath, $sourceFormatName = null){

        if (!is_null($sourceFormatName)) {
            $sourceFormatArray = $this->readFormatFile($sourceFormatName);
            if ($sourceFormatArray === false) {
                return false;
            }
        } else {
            $sourceFormatArray["sourceDataSet"]["sheet"] = 0;
            $sourceFormatArray["sourceDataSet"]["rowSet"]["dataStartRow"] = 3;
            $sourceFormatArray["sourceDataSet"]["rowSet"]["columnNameRow"] = 2;
        }

        $dataProcess = new dataProcess();
        if($dataProcess->initialize($sourceFormatArray["sourceDataSet"],$sourceFilePath) === false){
            print_r($dataProcess->getErrorList());
            return false;
        }


        $this->configArray = $sourceFormatArray;
        $this->dataProcess = $dataProcess;
        return true;
    }


    /**
     * @return bool|int
     * @throws Exception
     */
    function importDatabase($tableName = null){
        if(!is_null($tableName)){
            $this->configArray["tableName"] = $tableName;
        }
        $importRow = 0;
        if(is_null($this->databaseLink)){
            throw new Exception("Database is not connecting!");
        }
        if(is_null($this->dataProcess)){
            throw new Exception("Source file is not loading!");
        }
        $this->checkSourceFormatColumn();
        $this->databaseLink->autocommit(false);

        $this->databaseLink->query("truncate table ".$this->configArray["tableName"]);//清空表
        while(($sql = $this->getNextInsertSql()) !== true && $sql != false){
            //echo "<br />执行sql:".$sql;ob_flush();flush();
            $result = $this->databaseLink->query($sql);
//            echo $sql."<br />";
//            $result = true;
            if($result == false){
                $errorMsg = $this->dataProcess->getExcelCurrentLineNum()."行数据 sql执行失败:".$this->databaseLink->error;
                throw new Exception($errorMsg);
                $sql = false;
                break;
            }else{
                //echo " ----- 成功";ob_flush();flush();
                $importRow++;
            }
            //sleep(2);
        }


        if($sql)
        {
            $this->databaseLink->commit();
            return $importRow;
        }else{

            $this->databaseLink->rollback();
            return false;
        }

    }

    /**
     * 获取下一条数据的插入SQL语句
     * @return bool|string
     */
    function getNextInsertSql(){
        if(($data = $this->dataProcess->getNextRow()) === false){
            return true;
        }

        $keyNameArray = array_keys($this->dataProcess->getFormatConfig("columnSet"));
        $keyName = implode('`, `',$keyNameArray);
        $keyName = "`$keyName`";

        $tableName = $this->configArray["tableName"];
        $value = implode('\', \'',$data);
        $value = "'$value'";
        if(count($keyNameArray) != count($data)){
            return false;
        }

        $sql = "INSERT $tableName($keyName) VALUES($value);";
        return $sql;
    }

    /**
     * 检查配置文件的列名是否存在
     * @throws Exception
     */
    private function checkSourceFormatColumn(){
        $columnSet = $this->dataProcess->getFormatConfig("columnSet");
        $columnNameArray = array_keys($columnSet);
        $tableColumnArray = $this->getDatabaseTableColumn($this->configArray["tableName"]);
        $diffColumnList = array_diff($columnNameArray,$tableColumnArray);
        if(count($diffColumnList) > 0){
            echo "不存在的目标表列名：";
            echo implode(',',$diffColumnList)." ";
            if($this->importModel == self::IMPORT_DATA_MODEL_STRICT){
                throw new Exception("Have column name not find!");
            }elseif($this->importModel == self::IMPORT_DATA_MODEL_TOLERANCE){
                echo "<br />宽容模式-----忽略";
                if(count($diffColumnList) == count($columnNameArray)){
                    throw new Exception("Source File no columns name match!");
                }

                foreach($diffColumnList as $oneColumnName){
                    unset($columnSet[$oneColumnName]);
                }
                $this->dataProcess->setFormatConfig($columnSet,"columnSet");
            }
        }
    }

    /**
     * 获取目标表所有列名
     * @param $tableName
     * @return array|bool
     */
    private function getDatabaseTableColumn($tableName){
        $result = $this->databaseLink->query("SHOW FIELDS FROM $tableName");
        if($result == false){
            return false;
        }
        $result = mysqli_fetch_all($result);
        $columnList = array();
        foreach($result as $oneColumnName){
            $columnList[] = $oneColumnName[0];
        }
        return $columnList;
    }

    /**
     *
     */
    function __destruct()
    {
        //Implement __destruct() method.
        $this->databaseLink->close();
        unset($this->databaseLink);
        unset($this->dataProcess);
        unset($this->sourceFormatFileList);
    }

    /**
     * 连接数据库
     * @param $host
     * @param $username
     * @param $password
     * @param $database
     * @param $port
     */
    function connectDatabase($host, $username, $password, $database, $port,$charset = "utf8"){
        $mysql = new mysqli();
        $mysql->connect($host,$username,$password,$database,$port);
        $mysql->set_charset($charset);
        $this->databaseLink = $mysql;

    }

    /**
     * 读取数据源配置文件
     * @param $filename
     * @return bool|mixed
     */
    private function readFormatFile($filename)
    {
        if(!in_array($filename,$this->sourceFormatFileList))
        {
            return false;
        }
        $filePath = $this->sourceFormatDir."/$filename.".$this->sourceFormatExt;
        $configStr = file_get_contents($filePath);

        return json_decode($configStr,true);
    }

    /**
     *  设置数据源格式文件列表
     */
    private function setSourceFormatFileList()
    {
        $jsonFileList = array();
        if($dirHandle = opendir($this->sourceFormatDir)){
            while(false !== ($fileName = readdir($dirHandle))){
                if($fileName != "." && $fileName != ".." && !is_dir("./".$fileName)){
                    // echo $fileName."<br />";
                    $fileInfo = pathinfo("./$fileName");
                    if($fileInfo["extension"] == $this->sourceFormatExt)
                    {
                        $jsonFileList[] = $fileInfo["filename"];
                    }
                }
            }
        }
        $this->sourceFormatFileList = $jsonFileList;
    }
}